package com.erp.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.erp.common.CustomException;
import com.erp.common.R;
import com.erp.common.SuperConstant;
import com.erp.dao.*;
import com.erp.dto.UserDto;
import com.erp.entity.*;
import com.erp.entity.vo.ViewAction;
import com.erp.entity.vo.ViewManager;
import com.erp.service.*;
import com.erp.utils.DigestsUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements UserService {

    @Autowired
    private ManagerGroupService managerGroupService;

    @Autowired
    private UserGroupService userGroupService;

    @Autowired
    private ActionGroupService actionGroupService;

    @Autowired
    private ActionService actionService;

    /**
     * 用户注册 注册成功直接登陆
     *
     * @param map         封装传入的手机号和验证码
     * @param httpSession 用于返回用户信息
     * @return
     */
    @Override
    @Transactional
    public R<UserDto> register(Map<String, String> map, HttpSession httpSession) {
        //map中获取手机号
        String phone = map.get("phone");
        //map中获取验证码
        String code = map.get("code");
        //从Session获取保存的验证码
        Object codeInSession = httpSession.getAttribute(phone);
        //构造器根据name查询
        User byUsername = this.findByUsername(phone);
        //判断用户名是否存在
        if (byUsername != null) {
            return R.error("注册失败,用户名已存在");
        }
        //进行验证码对比
        if (codeInSession != null && codeInSession.equals(code)) {
            //对比成功 进行注册
            User user = new User();
            user.setUsername(phone);
            //设置初始密码 进行加密
            Map<String, String> stringMap = DigestsUtil.entryptPassword(SuperConstant.DefaultPassword);
            String salt = stringMap.get("salt");
            String password = stringMap.get("password");
            user.setSalt(salt);
            user.setPassword(password);
            //默认字段填充
            user.setStatus(0);
            //保存用户信息
            this.save(user);
            //获取用户id
            Long userId = this.findByUsername(phone).getId();
            //设置默认角色
            UserGroup userGroup = new UserGroup();
            userGroup.setUserId(userId);
            userGroup.setManagerId(SuperConstant.DefaultManagerId);
            userGroupService.save(userGroup);
            //从SecurityUtils里边创建一个 subject
            Subject subject = SecurityUtils.getSubject();
            //注册完成 直接进行执行登陆认证
            subject.login(new UsernamePasswordToken(user.getUsername(), SuperConstant.DefaultPassword));
            //将用户id写回给httpSession
            httpSession.setAttribute("user", userId);
            User byId = this.getById(userId);
            UserDto userDto = this.userDtoCopy(byId);
            return R.success(userDto);
        }
        //验证码对比失败
        return R.error("注册失败");
    }

    /**
     * 根据用户名称获取角色名称
     *
     * @param userName 用户名称
     * @return 角色名称
     */
    @Override
    public ViewManager findManagerByUsername(String userName) {
        //根据userName查询userId
        User user = this.findByUsername(userName);
        Long userId = user.getId();
        //根据userId查询ManagerId
        LambdaQueryWrapper<UserGroup> userGroupLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userGroupLambdaQueryWrapper.eq(UserGroup::getUserId, userId);
        //用list来接收条件构造器 为防止出现查询出多个数据导致抛出异常
        List<UserGroup> list = userGroupService.list(userGroupLambdaQueryWrapper);
        //如果list元素大于1 则找到多个managerId 抛出业务异常 并在全局异常处理器进行捕获
        if (list.size()>1){
            throw new CustomException("用户关联表异常，请联系管理员请求维护");
        }
        //获取唯一的userGroup
        UserGroup userGroup = list.get(0);
        if (userGroup == null) {
            return null;
        }
        //获取管理员id
        Long managerId = userGroup.getManagerId();
        //根据managerId查询managerName
        ManagerGroup managerGroup = managerGroupService.getById(managerId);
        String managerName = managerGroup.getManagerName();
        //把查询到的managerName封装到viewManager
        ViewManager viewManager = new ViewManager();
        viewManager.setUserName(userName);
        viewManager.setManager(managerName);
        return viewManager;
    }

    /**
     * 根据角色名称获取该角色拥有的权限
     *
     * @param managerName
     * @return
     */
    @Override
    public List<ViewAction> findActionByManagerId(String managerName) {
        //根据managerName查询managerId
        LambdaQueryWrapper<ManagerGroup> managerGroupLambdaQueryWrapper = new LambdaQueryWrapper<>();
        managerGroupLambdaQueryWrapper.eq(ManagerGroup::getManagerName, managerName);
        List<ManagerGroup> managerGroupList = managerGroupService.list(managerGroupLambdaQueryWrapper);

        if (managerGroupList.size()>1){
            throw new CustomException("管理员表异常，请联系管理员请求维护");
        }

        ManagerGroup managerGroup = managerGroupList.get(0);
        Long managerId = managerGroup.getManagerId();

        //根据managerId查询所有actionId
        LambdaQueryWrapper<ActionGroup> actionGroupLambdaQueryWrapper = new LambdaQueryWrapper<>();
        actionGroupLambdaQueryWrapper.eq(ActionGroup::getManagerId, managerId);
        List<Long> ids = new ArrayList<>();

        //把查询到的id存入ids集合
        for (ActionGroup actionGroup : actionGroupService.list(actionGroupLambdaQueryWrapper)) {
            ids.add(actionGroup.getActionId());
        }

        List<ViewAction> list = new ArrayList<>();
        //根据ids查询actionName 并把结构封装到ViewAction并存入list集合
        for (Action action : actionService.listByIds(ids)) {
            ViewAction viewAction = new ViewAction();
            viewAction.setAction(managerName + ":" + action.getActionName());
            System.out.println(viewAction.getAction());
            list.add(viewAction);
        }
        return list;
    }

    /**
     * 根据用户名查找用户
     *
     * @param username 用户名称
     * @return 用户对象
     */
    @Override
    public User findByUsername(String username) {
        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userLambdaQueryWrapper.eq(User::getUsername, username);
        List<User> list = this.list(userLambdaQueryWrapper);
        if (list.size()==1){
            return list.get(0);
        }else if (list.size()==0){
          return null;
        } else {
            throw new CustomException("用户表异常，请联系管理员请求维护");
        }
    }

    /**
     * 新增用户
     * @param user
     * @return
     */
    @Override
    @Transactional
    public R<String> add(User user) {
        String username = user.getUsername();
        User byUsername = this.findByUsername(username);
        if (byUsername!=null){
            return R.error("账号已存在");
        }
        //设置用户初始化密码 进行加密
        Map<String, String> map = DigestsUtil.entryptPassword(SuperConstant.DefaultPassword);
        String salt = map.get("salt");
        String password = map.get("password");
        user.setSalt(salt);
        user.setPassword(password);
        this.save(user);

        //设置默认角色
        UserGroup userGroup = new UserGroup();
        userGroup.setUserId(this.findByUsername(username).getId());
        userGroup.setManagerId(SuperConstant.DefaultManagerId);
        userGroupService.save(userGroup);
        return R.success("新增用户成功");
    }

    /**
     * 根据id删除用户
     * @param id
     * @return
     */
    @Override
    @Transactional
    public R<String> delete(Long id) {
        if (id==1){
            return R.error("无法删除默认管理员");
        }
        this.removeById(id);
        LambdaQueryWrapper<UserGroup> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(UserGroup::getUserId,id);
        userGroupService.remove(lambdaQueryWrapper);
        return R.success("删除成功");
    }

    @Override
    public UserDto userDtoCopy(User user) {
        UserDto userDto = new UserDto();
        BeanUtils.copyProperties(user,userDto);
        ViewManager managerByUsername = this.findManagerByUsername(user.getUsername());
        String manager = managerByUsername.getManager();
        userDto.setManagerName(manager);
        return userDto;
    }

}
